package by.ostrovsky.webhousingsystem.junit.hardcode;

import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import junit.framework.TestCase;

import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import by.ostrovsky.webhousingsystem.crypt.SHACrypt;
import by.ostrovsky.webhousingsystem.dao.DAOFactory;
import by.ostrovsky.webhousingsystem.dao.implementation.idao.IOperateDAO;
import by.ostrovsky.webhousingsystem.dao.implementation.idao.IReadDAO;
import by.ostrovsky.webhousingsystem.exception.OperationErrorException;
import by.ostrovsky.webhousingsystem.hibernate.entity.Account;
import by.ostrovsky.webhousingsystem.hibernate.entity.Employee;
import by.ostrovsky.webhousingsystem.hibernate.entity.UserRequest;

public class FillDBTest extends TestCase {
	private DAOFactory factory = null;
	private static Logger logger = Logger.getLogger(FillDBTest.class);
	private IOperateDAO<List<Account>, Boolean> accountcuddao = null;
	private IReadDAO<Account> accountreadalldao = null;
	private IOperateDAO<List<Employee>, Boolean> employeecuddao = null;
	private IOperateDAO<List<UserRequest>, Boolean> requestcuddao = null;
	private final int _userNumber = 50;
	private final int _requestNumber = 20;
	private final int _employeNumber = 100;
	private static Long c;
	private static int h;
	private static String specs[] = { "construction of monolithic concrete",
			"reinforced concrete structures",
			"engineering systems of buildings", "wooden structures",
			"masonry and reinforced masonry structures",
			"light frame structures", "external networks and structures",
			"steel erection",
			"anticorrosion coatings construction of buildings and structures",
			"device insulation coatings", "roofing",
			"foundations of buildings and structures" };

	// 1 - init users + session hash
	// 2 - init requested work
	// 3 - init employes
	// 4 - init taskgroups
	// 5 - init workplan

	@Before
	public void setUp() throws Exception {
		factory = DAOFactory.getDAOFactory(DAOFactory.MySQL);
		accountcuddao = factory.getAccountDAO();
		accountreadalldao = factory.getReadAccountDAO();
		employeecuddao = factory.getEmployeDAO();
		requestcuddao = factory.getHousingRequestDAO();
	}

	@After
	public void tearDown() throws Exception {
		factory = null;
		employeecuddao = null;
		accountcuddao = null;
		accountreadalldao = null;
		requestcuddao = null;
		specs = null;
		c = null;
	}

	@Test
	public void test() {
		try {
			fillAccountTable();
			fillEmployeeTable();
			fillRequestTable();
		} catch (Exception e) {
			fail(e.toString());
		}
	}

	public UserRequest generateRequest() {

		try {
			UserRequest request = new UserRequest();
			Date date = new Date();

			Calendar cal = Calendar.getInstance();
			cal.setTime(date);
			cal.set(Calendar.HOUR_OF_DAY, 0);
			cal.set(Calendar.MINUTE, 0);
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);

			long caltime = cal.getTimeInMillis();

			final int week = 604800000;
			int time = getRandInRange(week, week * 3);
			caltime += time;
			date.setTime(caltime);
			// deadline
			request.setDeadline(date);

			h += 5;
			String work = specs[h % 11];
			// requestedwork
			request.setWork(work);
			List<Account> list = new LinkedList<Account>();

			list = accountreadalldao.readAll();
			int index = getRandInRange(0, list.size());
			// request login
			Account acc = new Account();
			acc.setId(list.get(index).getId());
			request.setAccount(acc);

			int day = 86400000;
			date = new Date();
			long regdate = date.getTime() - getRandInRange(day, day * 3);
			date.setTime(regdate);
			// regdate
			request.setRegdate(date);
			// phone
			request.setPhone("+" + getRandInRange(1000000, 7000000));
			// addinfo
			request.setAddinfo("no add info");
			request.setId(++c);
			request.setAccepted(false);

			return request;
		} catch (Exception e) {
			logger.error(e);
		}
		return null;

	}

	public Account generateAccount() {
		Account account = new Account();
		int randYear, randDay, randMonth, rand;
		String login = "user", name = "username", mailsuffix = "@gmail.com";
		int accessLevel = 4;

		randYear = getRandInRange(1950, 1955);
		randDay = getRandInRange(1, 30);
		randMonth = getRandInRange(1, 12);
		rand = getRandInRange(1, _userNumber);

		login += randYear + randMonth + randDay + "_" + rand;
		name += randYear + randMonth + randDay + "_" + rand;

		try {
			account.setAccessLevel(accessLevel);
			account.setHashed(SHACrypt.getInstance().encrypt(login));
			account.setId(login);
			account.setMail(name + mailsuffix);
			account.setUserName(name);
		} catch (OperationErrorException e) {
			e.printStackTrace();
		}

		return account;
	}

	public Employee generateEmployee() {
		Employee employee = new Employee();
		int randYear, randDay, randMonth, rand;
		String firstname = "employe_firstname", lastname = "employee_lastname";
		Random random = new Random();
		Boolean isMaster = random.nextBoolean();
		Boolean isBusy = false;

		String spec = specs[getRandInRange(0, 11)];
		randYear = getRandInRange(1950, 1955);
		randDay = getRandInRange(1, 30);
		randMonth = getRandInRange(1, 12);
		rand = getRandInRange(1, _employeNumber);
		String total = randYear + randMonth + randDay + "_" + rand;

		employee.setId(++c);
		employee.setName(firstname + total);
		employee.setSurname(lastname + total);
		employee.setSpeciality(spec);
		employee.setIsMaster(isMaster);
		employee.setIsBusy(isBusy);

		return employee;
	}

	public static int getRandInRange(int min, int max) {
		return (int) (Math.random() * (max - min) + min);
	}

	public void fillAccountTable() throws Exception {
		try {
			c = new Long(0);
			List<Account> list = new LinkedList<Account>();
			for (int i = 0; i < _userNumber; i++) {
				Account acc = generateAccount();
				list.add(acc);
			}
			accountcuddao.create(list);
		} catch (Exception e) {
			fail();
			System.err.println(e.toString());
		}
	}

	public void fillEmployeeTable() throws Exception {

		try {
			c = new Long(0);
			List<Employee> list = new LinkedList<Employee>();
			for (int i = 0; i < _employeNumber; i++) {
				list.add(generateEmployee());
			}
			employeecuddao.create(list);
		} catch (Exception e) {
			fail();
			System.err.println(e.toString());
		}
	}

	public void fillRequestTable() throws Exception {
		try {
			c = new Long(0);
			List<UserRequest> list = new LinkedList<UserRequest>();
			for (int i = 0; i < _requestNumber; i++) {
				list.add(generateRequest());
			}
			requestcuddao.create(list);
		} catch (Exception e) {
			fail();
			logger.error(e);
		}
	}
}
